<?php


include_once($mcrp . 'config/config.php');
include_once($mcrp . 'functions/users.php');
include_once($mcrp . 'functions/nanovm.php');

class FightInfos
{
	var $id = 0;
	var $players = array();
	var $options = array();
	var $statut = '';
	var $exectime = 0;
}

function CreateFightFree($playercount)
{
	global $mcuser;
	$fi = new FightInfos;
	$fi->players = array(array($mcuser->id, 'ready', 0));
	while(--$playercount) $fi->players[] = array(0, 'free', 0);
	CreateFight($fi);
	return $fi;
}

function CreateFightPrivate($players)
{
	global $mcuser;
	$fi = new FightInfos;
	$fi->players = array(array($mcuser->id, 'ready', 0));
	foreach($players as $p) { $fi->players[] = array($p, 'wait', 0); NanoSendMail($mcuser, $p); }
	CreateFight($fi);
}

function NanoSendMail($creator, $id)
{
	$u = GetUserById($id);
	$mail = $u->email;
	$Titre = 'Défi NanoContest';
	$Text = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
	$Text .= '<html xmlns="http://www.w3.org/1999/xhtml">';
	$Text .= '<head><meta http-equiv="content-type" content="text/html; charset=UTF-8" /></head><body>';
	$Text .= '<h3>NanoContest</h3><br />';
	$Text .= $creator->name . ' vous lance un défi au NanoContest.<br />';
	$Text .= 'Rendez-vous sur <a href="http://www.microcontest.com/nanofight.php">cette page</a> si vous souhaiter le relever, afin de confirmer votre inscription.';
	$Text .= '</body></html>';
	$Headers  = 'MIME-Version: 1.0' . "\r\n";
	$Headers .= 'Content-type: text/html; charset=UTF-8' . "\r\n";
	$Headers .= 'From: Contact µContest <contact@microcontest.com>' . "\r\n" .
				'Reply-To: Contact µContest <contact@microcontest.com>' . "\r\n" .
				'X-Mailer: PHP/' . phpversion();
	return mail($mail, $Titre, $Text, $Headers);
}

function NanoSendMailReady($id)
{
	$u = GetUserById($id);
	$mail = $u->email;
	$Titre = 'Défi NanoContest';
	$Text = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
	$Text .= '<html xmlns="http://www.w3.org/1999/xhtml">';
	$Text .= '<head><meta http-equiv="content-type" content="text/html; charset=UTF-8" /></head><body>';
	$Text .= '<h3>NanoContest</h3><br />';
	$Text .= 'Les inscriptions sont terminées. Vous pouvez désormais envoyer votre programme en vous rendant sur <a href="http://www.microcontest.com/nanofight.php">cette page</a> puis en cliquant sur le bouton gérer en face de votre pseudo.';
	$Text .= '</body></html>';
	$Headers  = 'MIME-Version: 1.0' . "\r\n";
	$Headers .= 'Content-type: text/html; charset=UTF-8' . "\r\n";
	$Headers .= 'From: Contact µContest <contact@microcontest.com>' . "\r\n" .
				'Reply-To: Contact µContest <contact@microcontest.com>' . "\r\n" .
				'X-Mailer: PHP/' . phpversion();
	return mail($mail, $Titre, $Text, $Headers);
}

function MakePlayerList($players)
{
	function myImplode($ret,$current)
	{
		if($ret) $ret .= ';';
		return $ret .= implode(',',$current);
	}
	return array_reduce($players, 'myImplode');
}

function CreateFight(&$FightInfos)
{
	global $mcsql;
	$players = MakePlayerList($FightInfos->players);
	$result = $mcsql->Query('INSERT INTO nanofight(players, options, statut, exectime) VALUES(\'' . $players . '\', \'' . implode(";", $FightInfos->options) . '\', \'new\', \'' . time() . '\')');
	if($result === false) return false;
	$FightInfos->id = mysql_insert_id();
	return true;
}

function GetFightById($id)
{
	global $mcsql;
	$answer = $mcsql->Query('SELECT * FROM nanofight WHERE id=\'' . $id . '\'');
	if($f = mysql_fetch_array($answer))
	{
		$fi = FillFightInfos($f); 
		return $fi;
	}
	return false;
}

function GetFightByIdLite($id)
{
	global $mcsql;
	$answer = $mcsql->Query('SELECT * FROM nanofight WHERE id=\'' . $id . '\'');
	if($f = mysql_fetch_array($answer))
	{
		$fi = FillFightInfosLite($f); 
		return $fi;
	}
	return false;
}

function GetAllFightsByStatut()
{
	global $mcsql;
	$fights = array();
	$answer = $mcsql->Query('SELECT * FROM nanofight ORDER BY exectime DESC, id DESC');
	while($f = mysql_fetch_array($answer))
	{
		$fi = FillFightInfos($f);
		$fights[$fi->statut][$fi->id] = $fi;
	}
	return $fights;
}

function FillFightInfos($fight)
{
	$c = -1;
	$fi = new FightInfos;
	$fi->id = $fight['id'];
	$players = explode(";", $fight['players']);
	foreach($players as $p) { $p = explode(",", $p); $fi->players[($p[0]?$p[0]:$c--)] = $p; $fi->players[($p[0]?$p[0]:$c+1)][0] = GetUserById($p[0]); }
	$fi->options = explode(";", $fight['options']);
	$fi->statut = $fight['statut'];
	return $fi;
}

function FillFightInfosLite($fight)
{
	$c = -1;
	$fi = new FightInfos;
	$fi->id = $fight['id'];
	$players = explode(";", $fight['players']);
	foreach($players as $p) { $p = explode(",", $p); $fi->players[($p[0]?$p[0]:$c--)] = $p; }
	$fi->options = explode(";", $fight['options']);
	$fi->statut = $fight['statut'];
	return $fi;
}

function NanoRegisterPlayer($fight, $player)
{
	$fi = GetFightByIdLite($fight);
	if($fi === false) return false;
	if(array_key_exists($player, $fi->players)) return false;
	foreach($fi->players as $key => $p)
	{
		if($p[0] == 0)
		{
			$fi->players[$key] = array($player, 'ready', 0);
			CheckFightReady($fi);
			UpdateFightLite($fi);
			return true;
		}
	}
	return false;
}

function NanoConfirmRegisterPlayer($fight, $player)
{
	$fi = GetFightByIdLite($fight);
	if($fi === false) return false;
	if(!array_key_exists($player, $fi->players)) return false;
	$fi->players[$player][1] = 'ready';
	CheckFightReady($fi);
	UpdateFightLite($fi);
	return true;
}

function NanoDeclineRegisterPlayer($fight, $player)
{
	$fi = GetFightByIdLite($fight);
	if($fi === false) return false;
	if(!array_key_exists($player, $fi->players)) return false;
	unset($fi->players[$player]);
	UpdateFightLite($fi);
	return false;
}

function CheckFightReady(&$fi)
{
	foreach($fi->players as $p) if($p[1] != 'ready') return false;
	$fi->statut = 'ready';
	foreach($fi->players as $p)
		NanoSendMailReady($p[0]);
}

function UpdateFightLite($fi)
{
	global $mcsql;
	$players = MakePlayerList($fi->players);
	return $mcsql->Query('UPDATE nanofight SET players=\'' . $players . '\', options=\'' . implode(";", $fi->options) . '\', statut=\'' . $fi->statut . '\', exectime=' . $fi->exectime . ' WHERE id=' . $fi->id);
}

function NanoDeleteFight($id)
{
	global $mcsql;
	$mcsql->Query('DELETE FROM nanofight WHERE id=' . $id);
}

function SetFightProgram($fightid, $playerid, $code)
{
	$fight = GetFightByIdLite($fightid);
	if($fight == false) return false;
	if(!array_key_exists($playerid, $fight->players)) return false;
	$prgm = GetFightPrograms($fight->id);
	$prgm[$playerid] = $code;
	SetFightPrograms($fight->id, $prgm);
	$fight->players[$playerid][1] = 'prgm';
	UpdateFightLite($fight);
	return true;
}

function GetFightPrograms($id)
{
	global $mcrp;
	$file = $mcrp . 'nano/prgm/' . $id . '.fight';
	if(!file_exists($file)) return array();
	$data = file_get_contents($file);
	$data = explode(";", $data);
	$prgm = array();
	foreach($data as $p) { $p = explode(",", $p); $prgm[$p[0]] = $p[1]; }
	return $prgm;
}

function SetFightPrograms($id, $prgm)
{
	global $mcrp;
	$file = $mcrp . 'nano/prgm/' . $id . '.fight';
	$data = '';
	foreach($prgm as $id => $code)
		$data .= $id . ',' . $code . ';';
	$data = rtrim($data, ';');
	file_put_contents($file, $data);
}

function NanoPrepareFightExec($id)
{
	$fight = GetFightById($id);
	if($fight == false) return false;
	if($fight->statut != 'ready' && $fight->statut != 'done') return false;
	$prgm = GetFightPrograms($id);
	if($prgm == false) return false;
	if(count($prgm) != count($fight->players)) return false;
	foreach($fight->players as &$p) { $p['code'] = $prgm[$p[0]->id]; }
	$execinfos = array('id' => $id, 'players' => $fight->players, 'checkstop' => 'NanoFightCheckStop');
	if($fight->statut != 'done')
	{
		$execinfos['do'] = 'serverexec';
		$_SESSION['execinfos'] = $execinfos;
	}
	return $execinfos;
}

function NanoExecFightC($execinfos)
{
	$players = &$execinfos['players'];
	$wincount = array();
	$serverlog = '';
	for($i = 0; $i<11; $i++)
	{
		$cmd = 'do=exec&maxthread=3';
		foreach($players as $p)
		{
			$addr = rand(0, 32767);
			$cmd .= '&player=' . $p[0]->name . '|' . $p[0]->id . '|' . $addr . '|' . $p['code'];
		}
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, 'http://www.microcontest.com/cgi-bin/nanovm.cgi');
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $cmd);
		$result = curl_exec($ch);
		$data = explode("//", $result);
		curl_close($ch);
		if($data[1] != '0')
		{
			$players[intval($data[1])][2]++;
			$serverlog .= $data[0] . "\n--------------------------\n";
		}
	}
	
	uasort($players, function($p1, $p2) { if($p1[2] > $p2[2]) return -1; return 1; } );
	reset($players);
	list($firstid,$first) = each($players);
	$second = next($players);
	$log = '';
	foreach($players as $p)
	{
		$log .= $p[0]->name . ' (' . $p[2] . ")\n";
	}
	if($first == $second)
	{
		echo 'égalité//';
		echo $log;
		echo $serverlog;
		echo 'égalité';
		NanoEndFight($execinfos, 0);
	}
	else
	{
		$winner = $execinfos['players'][$firstid][0];
		echo $winner->name . '//';
		echo $log;
		echo $serverlog;
		echo 'winner : ' . $winner->name . '(' . $winner->id . ')';
		NanoEndFight($execinfos, $winner->id);
	}
}

function NanoExecFight($execinfos)
{
	$result = NanoExec($execinfos);
	if($result['stop'] == 'cyclelimit')
	{
		echo 'égalité' . '//';
		echo $result['log'];
		echo 'égalité';
		NanoEndFight($execinfos['id'], 0);
	}
	else
	{
		$winner = reset($result['vm']->prgm);
		echo $winner->name . '//';
		echo $result['log'];
		echo 'winner : ' . $winner->name . '(' . $winner->id . ')';
		NanoEndFight($execinfos['id'], $winner->id);
	}
}

function NanoEndFight($execinfos, $winner)
{
	$fi = GetFightByIdLite($execinfos['id']);
	if($fi == false) return false;
	$fi->statut = 'done';
	foreach($fi->players as $key => &$p)
	{
		$p[2] = $execinfos['players'][$key][2];
		$u = GetUserById($key);
		if($winner == $key) $u->nanowin++;
		else $u->nanodefeat++;
		UpdateUserNano($u);
	}
	if($winner != 0)
		$fi->players[$winner][1] = 'winner';
	$fi->exectime = time();
	UpdateFightLite($fi);
}

function GetFightComment($id)
{
	$file = $mcrp . 'nano/prgm/' . $id . '.comment';
	if(!file_exists($file)) return array('count' => 0, 'comment' => '');
	$data = file_get_contents($file);
	$count = substr_count($data, "</div>");
	return array('count' => $count, 'comment' => $data);
}

function AddFightComment($id, $comment)
{
	global $mcuser;
	$html = '<div><b>' . $mcuser->name . '</b> : ' . htmlentities(stripslashes($comment), ENT_COMPAT, 'UTF-8') . '<span class="nc_comment_date">[' . date('d/m/Y - H:i:s') . ']</span></div>';
	$file = $mcrp . 'nano/prgm/' . $id . '.comment';
	$data = '';
	if(file_exists($file)) $data = file_get_contents($file);
	$html .= $data;
	file_put_contents($file, $html);
}

?>